home *** CD-ROM | disk | FTP | other *** search
- /*
- File: UniversalHIDAPI.c
-
- Contains: HID Emulation glue code between the ADB SHIM and the USB Mouse HID Module
-
- Version: xxx put version here xxx
-
- Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include <Types.h>
- #include <Devices.h>
- #include <DriverServices.h>
- #include <Errors.h>
- #include <USB.h>
-
- #include "UniversalHIDModule.h" // this is the prototype for all HIDModules that follow the UHID spec
-
-
- #include "UniversalModule.h" // this is the header for our specific driver
-
- extern usbUniversalPBStruct myUniversalPB;
-
- // globals
- Boolean deviceIsClaimed = false;
- UHIDModuleConnectionID currentConnectionID = 0;
-
- RoutineDescriptor interruptCallback =
- BUILD_ROUTINE_DESCRIPTOR(uppUserFnProcInfo, DeferredNotifyRegisteredHIDUser);
-
- // entry points
- OSStatus UHIDInstallInterrupt(UHIDModuleConnectionID connectionID, UHIDInterruptProcPtr pInterruptProc, UInt32 refcon)
- {
- // only allow our current clien to do this
- if (connectionID != currentConnectionID)
- return permErr;
-
- // clear our ring buffer
- myUniversalPB.deferredHIDRing_Head = myUniversalPB.deferredHIDRing_Tail = 0;
-
- // log what we're gonna do
- if (pInterruptProc)
- USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine installed", myUniversalPB.interfaceRef);
- else
- USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine removed", myUniversalPB.interfaceRef);
-
- // actually change it
- myUniversalPB.pClientInterruptRoutine = pInterruptProc;
- myUniversalPB.clientRefCon = refcon;
- return noErr;
- }
-
- OSStatus UHIDControlDevice(UHIDModuleConnectionID connectionID, UInt32 theControlSelector, void * theControlData)
- {
- #pragma unused (theControlData)
-
- // only allow our current client to do this
- if (connectionID != currentConnectionID)
- return permErr;
-
- switch (theControlSelector)
- {
- case kUHIDRemoveInterruptHandle:
- USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine removed", myUniversalPB.interfaceRef);
- myUniversalPB.pClientInterruptRoutine = nil;
- break;
-
- default:
- return kUSBInternalErr;
- }
-
- return noErr;
- }
-
- OSStatus UHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
- {
- UInt16 * pTheID;
- UInt32 * pTheSize;
-
- // we don't need a connection, because we want anyone to be ablt to do these
-
- switch (theInfoSelector)
- {
- case kUHIDGetVenderID:
- pTheID = (UInt16*)theInfo;
- *pTheID = (UInt16)(USBToHostWord(myUniversalPB.deviceDescriptor.vendor));
- return noErr;
-
- case kUHIDGetProductID:
- pTheID = (UInt16*)theInfo;
- *pTheID = (UInt16)(USBToHostWord(myUniversalPB.deviceDescriptor.product));
- return noErr;
-
- case kUHIDGetMaxPacketSize:
- pTheSize = (UInt32*)theInfo;
- *pTheSize = (UInt32)(myUniversalPB.maxPacketSize);
- return noErr;
- }
-
- return kUSBUnknownRequestErr;
- }
-
- OSStatus UHIDGetHIDDescriptor ( UInt32 inDescriptorType,
- UInt32 inDescriptorIndex,
- UInt32 * ioBufferSize,
- void * outBuffer)
- {
- UInt32 bytesToCopy = *ioBufferSize;
- void * sourcePtr = nil;
- UInt32 index;
- OSStatus status = noErr;
-
- // we don't need a connection, because we want anyone to be ablt to do these
-
- // are we looking for the HID descriptor?
- if (inDescriptorType == kUSBHIDDesc || (inDescriptorType == 0 && inDescriptorIndex == 0))
- {
-
- if (bytesToCopy > myUniversalPB.hidDiscriptor.d.descLen)
- bytesToCopy = myUniversalPB.hidDiscriptor.d.descLen;
-
- sourcePtr = &myUniversalPB.hidDiscriptor;
- }
- else
- {
- Boolean foundIt = false;
-
- for (index = 0; index < myUniversalPB.hidOwnedDescriptorsCount; index++)
- {
- // are we indexing for a specific type?
- if (inDescriptorType != 0)
- {
- if (inDescriptorType == myUniversalPB.hidOwnedDiscriptors[index].type &&
- inDescriptorIndex == myUniversalPB.hidOwnedDiscriptors[index].typeIndex)
- foundIt = true;
- }
- // otherwise indexing across descriptors in general
- else if (inDescriptorIndex == index + 1)
- foundIt = true;
-
- if (foundIt)
- {
- if (bytesToCopy > myUniversalPB.hidOwnedDiscriptors[index].length)
- bytesToCopy = myUniversalPB.hidOwnedDiscriptors[index].length;
-
- sourcePtr = myUniversalPB.hidOwnedDiscriptors[index].descriptor;
- break;
- }
- }
- }
-
- if (sourcePtr)
- {
- *ioBufferSize = bytesToCopy;
- BlockMoveData(sourcePtr, outBuffer, bytesToCopy);
- }
- else
- status = fnfErr;
-
- return status;
- }
-
- OSStatus UHIDClaimDevice (UHIDModuleConnectionID * connectionID, UInt32 reserved)
- {
- #pragma unused (reserved)
-
- if (deviceIsClaimed) return openErr;
-
- deviceIsClaimed = true;
-
- *connectionID = ++currentConnectionID;
-
- return noErr;
- }
-
- OSStatus UHIDReleaseDevice (UHIDModuleConnectionID connectionID)
- {
- // only allow our current client to do this
- if (connectionID != currentConnectionID)
- return permErr;
-
- if (!deviceIsClaimed) return closErr;
-
- deviceIsClaimed = false;
- return noErr;
- }
-
- void NotifyRegisteredHIDUser(UInt8 hidReport[])
- {
- // don't bother deferring it if we don't have a client interrupt installed
- if (myUniversalPB.pClientInterruptRoutine)
- {
- // find the spot we're gonna put it
- UInt32 insertIndex = myUniversalPB.deferredHIDRing_Head;
-
- // increment and renormalize the head
- if (++myUniversalPB.deferredHIDRing_Head >= kDeferredHIDReportRingBufferSize)
- myUniversalPB.deferredHIDRing_Head = 0;
-
- // if its full, we throw out the oldest one by incrementing the tail
- if (myUniversalPB.deferredHIDRing_Head == myUniversalPB.deferredHIDRing_Tail)
- {
- // increment and renormalize the tail
- if (++myUniversalPB.deferredHIDRing_Tail >= kDeferredHIDReportRingBufferSize)
- myUniversalPB.deferredHIDRing_Tail = 0;
-
- // put in the expert log that we blew out our buffer
- USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: HID report ring buffer full", 0);
- }
-
- // copy the actual data into our ring buffer
- BlockMoveData (hidReport,
- &myUniversalPB.deferredHIDReports[insertIndex * kMaxHIDReportSize],
- myUniversalPB.maxPacketSize);
-
- // defer until virtual memory safe time (so our clients don't have to be marked resident)
- DeferUserFn(&interruptCallback,0);
- }
- }
-
- void DeferredNotifyRegisteredHIDUser(void * unused)
- {
- #pragma unused(unused)
-
- // find the spot from which we're gonna remove it
- UInt32 removeIndex = myUniversalPB.deferredHIDRing_Tail;
-
- // check to see if we're empty, if so, something weird happened, so log it and exit
- if (myUniversalPB.deferredHIDRing_Tail == myUniversalPB.deferredHIDRing_Head)
- {
- // put in the expert log that we blew out our buffer
- USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: HID report ring buffer unexpectedly empty", 0);
-
- // bail out
- return;
- }
-
- // call our client, if installed
- if (myUniversalPB.pClientInterruptRoutine)
- {
- (*myUniversalPB.pClientInterruptRoutine)(
- (void *) &myUniversalPB.deferredHIDReports[removeIndex * kMaxHIDReportSize],
- myUniversalPB.clientRefCon);
- }
-
- // increment and renormalize the tail
- if (++myUniversalPB.deferredHIDRing_Tail >= kDeferredHIDReportRingBufferSize)
- myUniversalPB.deferredHIDRing_Tail = 0;
-
- }
-
- UHIDModuleDispatchTable TheUHIDModuleDispatchTable =
- {
- kCurrentDispatchTableVersion,
- kOldestCompatableDispatchTableVersion,
- 0x05ac, // Apple
- 0,
- 0,
- (UHIDGetDeviceInfoProcPtr) UHIDGetDeviceInfo,
- (UHIDClaimDeviceProcPtr) UHIDClaimDevice,
- (UHIDReleaseDeviceProcPtr) UHIDReleaseDevice,
- (UHIDInstallInterruptProcPtr) UHIDInstallInterrupt,
- (UHIDControlDeviceProcPtr) UHIDControlDevice,
- (UHIDGetHIDDescriptorProcPtr) UHIDGetHIDDescriptor
- };
-